package fr.utbm.gi.vi51.project.gui;

import java.awt.Container;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

import fr.utbm.gi.vi51.framework.FrameworkLauncher;
import fr.utbm.gi.vi51.framework.environment.Environment;
import fr.utbm.gi.vi51.framework.gui.FrameworkGUI;
import fr.utbm.gi.vi51.project.GlobalSettings;
import fr.utbm.gi.vi51.project.agent.EnemyMarine;
import fr.utbm.gi.vi51.project.agent.Leader;
import fr.utbm.gi.vi51.project.agent.Marine;
import fr.utbm.gi.vi51.project.agent.Mutalisk;
import fr.utbm.gi.vi51.project.agent.Zergling;
import fr.utbm.gi.vi51.project.environment.EnvironmentObject;
import fr.utbm.gi.vi51.project.environment.EnvironmentType;
import fr.utbm.gi.vi51.project.environment.MapLoader;
import fr.utbm.gi.vi51.project.environment.WorldModel;
import fr.utbm.gi.vi51.project.formations.FormationBody;
import fr.utbm.gi.vi51.project.formations.FormationOrientation;
import fr.utbm.gi.vi51.project.formations.SquareFormation;

public class SettingsDialog extends JFrame {
	private static final long serialVersionUID = -3357803276777755389L;
	protected static MapLoader mapLoader;
	protected static boolean ableToStart;
	protected static int loadedMapIndex;
	protected static JComboBox<String> mapComboBox;
	protected static JTextField zerglingAmount;
	protected static JTextField marineEnemyAmount;
	protected static JTextField mutaliskAmount;
	protected static JTextField marineAmount;
	protected static JLabel zerglingLabel;
	protected static JLabel marineEnemyLabel;
	protected static JLabel mutaliskLabel;
	protected static JLabel marineLabel;
	protected static JCheckBox enableWayPoint;
	protected static JCheckBox enableSmartFormation;
	protected static JLabel enableWayPointLabel;
	protected static JLabel enableSmartFormationLabel;

	/* Interface */
	JButton startButton;

	public SettingsDialog() {
		mapLoader = new MapLoader();
		ableToStart = false;

		this.setTitle("Settings"); //$NON-NLS-1$
		this.setSize(600, 300);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container contentPane = getContentPane();
		contentPane.setLayout(null);
		Insets insets = contentPane.getInsets();

		/* Units selection */
		zerglingAmount = new JTextField("0"); //$NON-NLS-1$
		contentPane.add(zerglingAmount);
		zerglingAmount.setBounds(450, 50, 30, 30);
		zerglingLabel = new JLabel("Zergling :"); //$NON-NLS-1$
		contentPane.add(zerglingLabel);
		zerglingLabel.setBounds(388, 50, 60, 30);

		marineEnemyAmount = new JTextField("0"); //$NON-NLS-1$
		contentPane.add(marineEnemyAmount);
		marineEnemyAmount.setBounds(450, 90, 30, 30);
		marineEnemyLabel = new JLabel("Marine Enemy :"); //$NON-NLS-1$
		contentPane.add(marineEnemyLabel);
		marineEnemyLabel.setBounds(354, 90, 90, 30);

		mutaliskAmount = new JTextField("0"); //$NON-NLS-1$
		contentPane.add(mutaliskAmount);
		mutaliskAmount.setBounds(450, 130, 30, 30);
		mutaliskLabel = new JLabel("Mutalisk :"); //$NON-NLS-1$
		contentPane.add(mutaliskLabel);
		mutaliskLabel.setBounds(385, 130, 60, 30);

		marineAmount = new JTextField("0"); //$NON-NLS-1$
		contentPane.add(marineAmount);
		marineAmount.setBounds(70, 100, 30, 30);
		marineLabel = new JLabel("Marine :"); //$NON-NLS-1$
		contentPane.add(marineLabel);
		marineLabel.setBounds(16, 100, 50, 30);

		/* smartform & waypoints */
		enableWayPoint = new JCheckBox();
		contentPane.add(enableWayPoint);
		enableWayPoint.setBounds(150, 150, 20, 20);
		enableWayPointLabel = new JLabel("Enable WayPoint :"); //$NON-NLS-1$
		contentPane.add(enableWayPointLabel);
		enableWayPointLabel.setBounds(47, 150, 150, 20);

		enableSmartFormation = new JCheckBox();
		contentPane.add(enableSmartFormation);
		enableSmartFormation.setBounds(150, 180, 20, 20);
		enableSmartFormationLabel = new JLabel("Enable SmartFormation :"); //$NON-NLS-1$
		contentPane.add(enableSmartFormationLabel);
		enableSmartFormationLabel.setBounds(10, 180, 160, 20);

		/* Map selection */
		mapComboBox = new JComboBox<>();
		for (int i = 0; i < mapLoader.size(); ++i) {
			mapComboBox.addItem(mapLoader.get(i).getName());
		}
		contentPane.add(mapComboBox);
		mapComboBox.setBounds(70, 50, 200, 30);

		JLabel mapLabel = new JLabel("Map :"); //$NON-NLS-1$
		contentPane.add(mapLabel);
		mapLabel.setBounds(30, 50, 50, 30);

		/* Start button */
		this.startButton = new JButton("Start"); //$NON-NLS-1$
		contentPane.add(this.startButton);
		this.startButton.setBounds(300 - 50 + insets.left, 200 - 15 + insets.left, 100, 30);

		this.startButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				loadedMapIndex = mapLoader.indexOf((String) mapComboBox.getSelectedItem());
				ableToStart = true;
				try {
					GlobalSettings.ZERGLING_COUNT = Integer.parseInt(zerglingAmount.getText());
					GlobalSettings.ENEMY_MARINE_COUNT = Integer.parseInt(marineEnemyAmount.getText());
					GlobalSettings.MUTALISK_COUNT = Integer.parseInt(mutaliskAmount.getText());
					GlobalSettings.MARINE_COUNT = Integer.parseInt(marineAmount.getText());
				} catch (NumberFormatException e) {
					System.out.println("Caught NumberFormatException. Please enter an integer value."); //$NON-NLS-1$
					return;
				}

				GlobalSettings.useWayPoints = enableWayPoint.isSelected();
				GlobalSettings.smartFormation = enableSmartFormation.isSelected();

				GlobalSettings.MAP_ID = SettingsDialog.getLoadedMapIndex();

				// Initializes Formation
				FormationBody squareBody = new SquareFormation(FormationOrientation.EAST);

				// Initializes World and GUI
				FrameworkGUI gui = new GUI(GlobalSettings.WORLD_SIZE_X, GlobalSettings.WORLD_SIZE_Y);
				Environment environment = new WorldModel(GlobalSettings.WORLD_SIZE_X - GlobalSettings.MENU_SIZE_X,
						GlobalSettings.WORLD_SIZE_Y);
				FrameworkLauncher.launchEnvironment(environment, gui, GlobalSettings.EXECUTION_DELAY);

				// Create map
				MapLoader ml = new MapLoader();
				ml.launch(GlobalSettings.MAP_ID);

				// Initializes Marines
				Leader leader = null;
				if (GlobalSettings.useWayPoints) {
					leader = new Leader(squareBody, 0, ml.getWayPointList(GlobalSettings.MAP_ID));

					WorldModel.setTarget(new EnvironmentObject(48, 100, 200, EnvironmentType.TARGET, 48, 48));
					FrameworkLauncher.launchEnvironmentObject(WorldModel.getTarget());
				} else {
					leader = new Leader(squareBody, 0, null);
				}

				WorldModel.addMarine(leader);
				FrameworkLauncher.launchAgent(leader);
				for (int i = 1; i < GlobalSettings.MARINE_COUNT; i++) {
					Marine marine = new Marine(squareBody, i);
					WorldModel.addMarine(marine);
					FrameworkLauncher.launchAgent(marine);
				}

				// Initializes Enemies
				for (int i = 0; i < GlobalSettings.ENEMY_MARINE_COUNT; i++) {
					EnemyMarine enemy = new EnemyMarine();
					FrameworkLauncher.launchAgent(enemy, mapLoader.getSpawnSpot(GlobalSettings.MAP_ID, 1).getX(),
							mapLoader.getSpawnSpot(GlobalSettings.MAP_ID, 1).getY());
				}

				for (int i = 0; i < GlobalSettings.ZERGLING_COUNT; i++) {
					Zergling zergling = new Zergling();
					FrameworkLauncher.launchAgent(zergling, mapLoader.getSpawnSpot(GlobalSettings.MAP_ID, 0).getX(),
							mapLoader.getSpawnSpot(GlobalSettings.MAP_ID, 0).getY());
				}

				for (int i = 0; i < GlobalSettings.MUTALISK_COUNT; i++) {
					Mutalisk mutalisk = new Mutalisk();
					FrameworkLauncher.launchAgent(mutalisk, mapLoader.getSpawnSpot(GlobalSettings.MAP_ID, 2).getX(),
							mapLoader.getSpawnSpot(GlobalSettings.MAP_ID, 2).getY());
				}

				// Scale formations
				squareBody.scale(GlobalSettings.MARINE_COUNT);
				// Start Simulation
				FrameworkLauncher.startSimulation();

			}
		});
	}

	public static boolean isAbleToStart() {
		return ableToStart;
	}

	public static int getLoadedMapIndex() {
		return loadedMapIndex;
	}

}
